package com.example.criminalintent.view

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Bundle
import android.provider.ContactsContract
import android.provider.MediaStore
import android.text.format.DateFormat
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.CheckBox
import android.widget.ImageButton
import android.widget.ImageView
import androidx.core.content.FileProvider
import androidx.core.widget.addTextChangedListener
import androidx.fragment.app.Fragment
import com.example.criminalintent.R
import com.example.criminalintent.model.Crime
import com.example.criminalintent.model.CrimeLab
import kotlinx.android.synthetic.main.fragment_crime.view.*
import java.io.File
import java.util.*
import com.example.criminalintent.util.PictureUtils


class CrimeFragment : Fragment() {

    private lateinit var mCrime: Crime
    private lateinit var mDateButton: Button
    private lateinit var mReportButton: Button
    private lateinit var mSuspectButton: Button
    private lateinit var mPhotoButton: ImageButton
    private lateinit var mPhotoView: ImageView
    private var mPhotoFile: File? = null
    private var mCallbacks: Callbacks? = null


    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = inflater.inflate(R.layout.fragment_crime, container, false)

        view.crime_title.setText(mCrime.mTitle)

        view.crime_title.addTextChangedListener(onTextChanged = { text: CharSequence?, _: Int, _: Int, _: Int ->
            mCrime.mTitle = text.toString()
            updateCrime()
        })

        mDateButton = view.findViewById(R.id.crime_date)
        updateDate()
        mDateButton.setOnClickListener {
            val manager = fragmentManager
            val datePickerFragment = DatePickerFragment.newInstance(mCrime.mDate!!)
            manager?.let { it1 ->
                datePickerFragment.setTargetFragment(
                    this,
                    REQUEST_DATE
                )
                datePickerFragment.show(it1, DIALOG_DATE)
            }
        }

        val mSolvedCheckBox = view.findViewById<CheckBox>(R.id.crime_solved)
        mSolvedCheckBox.isChecked = mCrime.mSolved
        mSolvedCheckBox.setOnCheckedChangeListener { _, isChecked ->
            mCrime.mSolved = isChecked
            updateCrime()
        }

        mReportButton = view.findViewById(R.id.crime_report)

        mReportButton.setOnClickListener {
            var intent = Intent(Intent.ACTION_SEND).apply {
                type = "text/plain"
                putExtra(Intent.EXTRA_TEXT, getCrimeReport())
                putExtra(Intent.EXTRA_SUBJECT, getString(R.string.crime_report_suspect))
            }
            intent = Intent.createChooser(intent, getString(R.string.send_report))
            startActivity(intent)
        }

        val pickContact = Intent(Intent.ACTION_PICK, ContactsContract.Contacts.CONTENT_URI)
        mSuspectButton = view.findViewById(R.id.crime_suspect)
        mSuspectButton.setOnClickListener {
            startActivityForResult(pickContact, REQUEST_CONTACT)
        }
        if (mCrime.mSuspect != null) {
            mSuspectButton.text = mCrime.mSuspect
        }

        val packageManager = activity!!.packageManager
        if (packageManager.resolveActivity(
                pickContact,
                PackageManager.MATCH_DEFAULT_ONLY
            ) == null
        ) {
            mSuspectButton.isEnabled = false
        }

        mPhotoButton = view.findViewById(R.id.crime_camera)
        val captureImage = Intent(MediaStore.ACTION_IMAGE_CAPTURE)

        val canTakePhoto =
            mPhotoFile != null && captureImage.resolveActivity(packageManager) != null
        mPhotoButton.isEnabled = canTakePhoto
        mPhotoButton.setOnClickListener {
            val uri = FileProvider.getUriForFile(
                activity!!,
                "com.example.criminalintent.fileprovider",
                mPhotoFile!!
            )
            captureImage.putExtra(MediaStore.EXTRA_OUTPUT, uri)
            val intentActivities = activity!!.packageManager.queryIntentActivities(
                captureImage,
                PackageManager.MATCH_DEFAULT_ONLY
            )
            for (a in intentActivities) {
                activity!!.grantUriPermission(
                    a.activityInfo.packageName,
                    uri,
                    Intent.FLAG_GRANT_WRITE_URI_PERMISSION
                )
            }
            startActivityForResult(captureImage, REQUEST_PHOTO)
        }

        mPhotoView = view.findViewById(R.id.crime_photo)
        updatePhotoView()

        return view
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val crimeId = arguments?.getSerializable(ARG_CRIME_ID) as UUID
        mCrime = CrimeLab[activity!!].getCrime(crimeId)!!
        mPhotoFile = CrimeLab[activity!!].getPhotoFile(mCrime)
    }

    companion object {

        const val ARG_CRIME_ID = "crime_id"
        const val DIALOG_DATE = "DialogDate"
        const val REQUEST_DATE = 0
        const val REQUEST_CONTACT = 1
        const val REQUEST_PHOTO = 2


        fun newInstance(crimeId: UUID): CrimeFragment {
            val bundle = Bundle()
            bundle.putSerializable(ARG_CRIME_ID, crimeId)
            val crimeFragment = CrimeFragment()
            crimeFragment.arguments = bundle
            return crimeFragment
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        if (resultCode != Activity.RESULT_OK) return

        if (requestCode == REQUEST_DATE) {
            val date = data?.getSerializableExtra(DatePickerFragment.EXTRA_DATE) as Date
            mCrime.mDate = date
            updateCrime()
            updateDate()
        } else if (requestCode == REQUEST_CONTACT && data != null) {
            val contactUri = data.data as Uri
            // Specify which fields you want your query to return values for.
            val queryFields = arrayOf(ContactsContract.Contacts.DISPLAY_NAME)
            // Perform your query - the contactUri is like a "where" clause here
            val cursor = activity?.contentResolver?.query(contactUri, queryFields, null, null, null)

            cursor.use {
                if (it!!.count == 0) {
                    return
                }
                it.moveToFirst()
                val suspect = it.getString(0)
                mCrime.mSuspect = suspect
                updateCrime()
                mSuspectButton.text = suspect
            }
        } else if (requestCode == REQUEST_PHOTO) {
            val uri = FileProvider.getUriForFile(
                activity!!,
                "com.example.criminalintent.fileprovider",
                mPhotoFile!!
            )
            activity!!.revokeUriPermission(uri, Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
            updateCrime()
            updatePhotoView()
        }
    }

    private fun updateCrime() {
        CrimeLab[activity!!].updateCrime(mCrime)
        mCallbacks!!.onCrimeUpdate(mCrime)
    }

    private fun updateDate() {
        mDateButton.text = DateFormat.format(getString(R.string.date_format), mCrime.mDate)
    }

    override fun onPause() {
        super.onPause()
        activity?.let { CrimeLab[it].updateCrime(mCrime) }
    }

    private fun getCrimeReport(): String {
        val solvedString: String = if (mCrime.mSolved) {
            getString(R.string.crime_report_solved)
        } else {
            getString(R.string.crime_report_unsolved)
        }
        val dateFormat = "yyy/mm/dd HH:MM:ss"
        val dateString = DateFormat.format(dateFormat, mCrime.mDate).toString()
        var suspect: String? = mCrime.mSuspect
        suspect = if (suspect == null) {
            getString(R.string.crime_report_no_suspect)
        } else {
            getString(R.string.crime_report_suspect, suspect)
        }

        return getString(R.string.crime_report, mCrime.mTitle, dateString, solvedString, suspect)
    }

    private fun updatePhotoView() {
        if (mPhotoFile == null || !mPhotoFile!!.exists()) {
            mPhotoView.setImageDrawable(null)
        } else {
            val bitmap = PictureUtils.getScaledBitmap(
                mPhotoFile!!.path, activity!!
            )
            mPhotoView.setImageBitmap(bitmap)
        }
    }

    interface Callbacks {
        fun onCrimeUpdate(crime: Crime)
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        mCallbacks = context as Callbacks
    }

    override fun onDetach() {
        super.onDetach()
        mCallbacks = null
    }
}